package com.example.javaserve.service.impl;

import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.extra.template.Template;
import cn.hutool.extra.template.TemplateConfig;
import cn.hutool.extra.template.TemplateEngine;
import cn.hutool.extra.template.TemplateUtil;
import com.example.javaserve.dto.AuthUserLoginDto;
import com.example.javaserve.entity.UserBaseInfo;
import com.example.javaserve.handler.password.PasswordEncoder;
import com.example.javaserve.result.Result;
import com.example.javaserve.result.impl.ErrorResult;
import com.example.javaserve.result.impl.SuccessResult;
import com.example.javaserve.service.AuthService;
import com.example.javaserve.service.EmailService;
import com.example.javaserve.dto.AuthUserDto;
import com.example.javaserve.dto.EmailDto;
import com.example.javaserve.utils.RSAUtils;
import com.example.javaserve.utils.RedisUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.jdbc.Null;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;

/**
 * @projectName: my_project
 * @package: com.example.javaserve.service.impl
 * @className: AuthServiceImpl
 * @author: xxXPCSC
 * @description: TODO
 * @date: 2023/11/15 16:02
 * @version: 1.0
 **/
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class AuthServiceImpl implements AuthService {

    // 验证码放入redis缓存过期时间
    @Value("${code.expiration}")
    private Long expiration;
    @Value("${rsa.private-key}")
    private String privateKey;

    private final RedisUtil redisUtils;
    private final EmailService emailService;
    private final PasswordEncoder passwordEncoder;
    private final UserCRUDImpl sysUserService;

    @Override
    public Result sendMailCode(String email) {

        // 查看注册邮箱是否存在
        if (sysUserService.registerEmailExist(email)) {
            return new ErrorResult("邮箱已经被注册");
        }


        // 获取发送邮箱验证码的HTML模板
        TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig("template", TemplateConfig.ResourceMode.CLASSPATH));
        Template template = engine.getTemplate("email-code.ftl");

        // 从redis缓存中尝试获取验证码
        Object code = redisUtils.get(email);
        if (code == null) {
            // 如果在缓存中未获取到验证码，则产生6位随机数，放入缓存中
            code = RandomUtil.randomNumbers(6);
            if (!redisUtils.set(email, code, expiration)) {
                return new ErrorResult("后台缓存服务异常");
            }
        }
        // 发送验证码
        emailService.send(new EmailDto(Collections.singletonList(email),
                "邮箱验证码", template.render(Dict.create().set("code", code))));
        return new SuccessResult("验证码发送成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result register(AuthUserDto authUserDto) {
        // 通过email获取redis中的code
        Object value = redisUtils.get(authUserDto.getEmail());
        if (value == null || !value.toString().equals(authUserDto.getCode())) {
            return new ErrorResult("无效验证码");
        } else {
            redisUtils.del(authUserDto.getEmail());
        }

        // 如果前端没有传入用户名，则以邮箱号作为用户名进行注册
        String userName = StringUtils.isEmpty(authUserDto.getUsername()) ? authUserDto.getEmail() : authUserDto.getUsername();

        if (sysUserService.findByUserName(userName) != null) {
            return new ErrorResult("用户名已存在");
        }
        System.out.println(authUserDto);
        // 创建用户
        UserBaseInfo sysUser = new UserBaseInfo();
        sysUser.setInfoUsername(userName);
        try {
            sysUser.setInfoPassword(passwordEncoder.encode(RSAUtils.decryptByPrivateKey(privateKey, authUserDto.getPassword())));
        } catch (Exception e) {
            return new ErrorResult("注册密码异常");
        }
        sysUser.setInfoEmail(authUserDto.getEmail());
        sysUser.setInfoRole(authUserDto.getRole());
        sysUser.setInfoSex(authUserDto.getSex());
        return sysUserService.create(sysUser);
    }

    @Override
    public Result login(AuthUserLoginDto authUserLoginDto) {
        String username = authUserLoginDto.getUsername();
        String password = authUserLoginDto.getUsername();
        return sysUserService.passwordIsRight(username,password);
    }


}
